#include <iostream>
#include <cstring>
#include <opencv2/opencv.hpp>
#include <vector>
#include <fstream>
#include <cmath>
#define PI 3.141592
using namespace std;
using namespace cv;

// 原图路径
static string originPath = "pic.jpg";
// 背景图片
static string blackground = "blackground";
// 结果图路径
static string resultPath = "result.jpg";
// 视频路径
static string vedioPath = "mask.avi";
/*
	图片旋转
*/
void transround(Mat &src,double ang){   
    Point2f center(src.cols / 2, src.rows / 2);    
    Mat rotMat = cv::getRotationMatrix2D(center,ang,1); 
    Rect bbox = RotatedRect(center, src.size(), ang).boundingRect();
    rotMat.at<double>(0, 2) += bbox.width / 2.0 - center.x;
    rotMat.at<double>(1, 2) += bbox.height / 2.0 - center.y;
    warpAffine(src,src,rotMat,bbox.size());
}
/*
	图片合成
*/
void copypic(Mat &originPic,Mat &blackgroundPic,float minwidth,float minheight,float width,float height){
	Mat defineReat; //图片合成的指定位置
    Size size(originPic.cols, originPic.rows);
    resize(originPic,originPic,Size(width, height),0,0,INTER_LINEAR); 
    
    Rect rect = Rect(minwidth, minheight, width, height);
    //在设置合成区域
    defineReat = blackgroundPic(rect);
    //将待拷贝图像拷贝到合成区域中
    originPic.copyTo(defineReat);
}

struct  oneFramePointGroup
{
	int frameNum;  		//帧数
	Point2f Points[4];	//4个点
};

void readFrameMsg(vector<oneFramePointGroup> &frameGroup){
	ifstream runway;
	runway.open ("point.txt");
	string pointNum;
	//存放运动轨迹数据的容器
	int i,j;
	for (i = 0;i < 4;i++){
		runway >> pointNum;
		for (j = 0;j < 90;j++){
			if (i != 0){
				runway >> frameGroup[j].frameNum;
				runway >> frameGroup[j].Points[i].x;
				runway >> frameGroup[j].Points[i].y;
			}else{
				float x,y;int num;oneFramePointGroup  tempFrame;
				runway >> num >> x >> y;
				tempFrame.frameNum = num;
				tempFrame.Points[i].x = x;
				tempFrame.Points[i].y = y;
				frameGroup.push_back(tempFrame);
			}
		}
	}
	
	runway.close();
}

void makevideoPic(Mat &resultPic,Mat &blackgroundPic,Mat &choosePic){
	/*
		遍历每个像素点
    */
	//遍历所有像素并设置像素值
    MatIterator_<Vec3b> modelit, modelend;
    MatIterator_<Vec3b> resultit, resultend;
    MatIterator_<uchar> chooseit, chooseend;
    resultit = resultPic.begin<Vec3b>();resultend = resultPic.end<Vec3b>();
    modelit = blackgroundPic.begin<Vec3b>();modelend = blackgroundPic.end<Vec3b>();
    chooseit = choosePic.begin<uchar>();chooseend = choosePic.end<uchar>();
    for( ;chooseit != chooseend; ++resultit,++modelit,++chooseit)
    {
    	if ((*chooseit)  >= 200){
    		 (*resultit)[0] = (*modelit)[0];
    		 (*resultit)[1] = (*modelit)[1];
    		 (*resultit)[2] = (*modelit)[2];

    	}
    }
}


int main(void)
{
	/*
		读取图片运动轨迹
	*/
	vector<oneFramePointGroup> frameGroup;
	readFrameMsg(frameGroup);
	vector<oneFramePointGroup>::iterator it;
	//读取图片与视频
	Mat originPic = imread("pic.jpg");
    Mat blackgroundPic = imread("blackground.jpg");
    Mat resultPic,choosePic;
    VideoCapture mask("mask.avi");
    VideoCapture model("test.mp4");
    /*
		遍历vector中所有点
	*/
	double angle,maxwidth,maxheight,minwidth,minheight;
	int nowFrameNum = 0;
	it = frameGroup.begin();
	while(1){
		mask >> choosePic;
		model >> resultPic;
		//获取当前帧数
		model.set(CV_CAP_PROP_POS_FRAMES, nowFrameNum++);
		if ((*it).frameNum == nowFrameNum){
			float widthArr[4] = {(*it).Points[0].x,(*it).Points[1].x,(*it).Points[2].x,(*it).Points[3].x};
			double heightArr[4] = {(*it).Points[0].y,(*it).Points[1].y,(*it).Points[2].y,(*it).Points[3].y};
			angle = atan(((*it).Points[0].y-(*it).Points[1].y)/((*it).Points[0].x-(*it).Points[1].x))*180/PI*-1;
			maxwidth = *max_element(widthArr,widthArr+4);
			minwidth = *min_element(widthArr,widthArr+4);
			maxheight = *max_element(heightArr,heightArr+4);
			minheight = *min_element(heightArr,heightArr+4);
			transround(originPic,angle);
    		copypic(originPic,blackgroundPic,minwidth,minheight,maxwidth-minwidth,maxheight-minheight);
    		makevideoPic(resultPic,blackgroundPic,choosePic);
    		originPic.release();
    		originPic = imread("pic.jpg");
    		IplImage tempimg = IplImage(resultPic);
		    cvSmooth(&tempimg, &tempimg, CV_MEDIAN, 3, 3, 0, 0); 
		 	//    //test  显示图片
		    string winname = "图片合成";
		    namedWindow(winname, 0);
		    imshow(winname, resultPic);
		    waitKey(1);
		    if (it != frameGroup.end()){
				it++;
			}
		}
		if (resultPic.empty()){
			break;
		}
		choosePic.release();
		resultPic.release();
	}
	mask.release();
	model.release();
    return 0;
}